﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace PBGenerator
{
    internal class Program
    {
        public static string getAppPath()
        {
            return AppDomain.CurrentDomain.BaseDirectory;
        }

        private static string getProtocPath()
        {
            return Program.getAppPath() + "\\protoc\\protoc";
        }

        private static string getProtoGenPath()
        {
            return Program.getAppPath() + "\\protogen\\protogen";
        }

        private static string getPrecompilePath()
        {
            return Program.getAppPath() + "\\precompile\\precompile";
        }

        private static string getProtoFilePath()
        {
            return Program.getAppPath() + "ProtoFile";
        }

        private static string getCommProtoFilePath(string fileName)
        {
            return Program.getProtoFilePath() + "\\" + fileName;
        }

        private static string getDotNet2Path()
        {
            string systemdir = Environment.GetFolderPath(Environment.SpecialFolder.System);
            string windir = Path.GetDirectoryName(systemdir);
            return windir + "\\Microsoft.NET\\Framework\\v2.0.50727";
        }

        private static void waitKeyForExit()
        {
            Console.WriteLine("按任意键退出！！！");
            Console.ReadKey();
            Environment.Exit(0);
        }

        public static void writeInfo(string info)
        {
            Console.WriteLine(info);
        }

        private static void Main(string[] args)
        {
            args = new string[5] { "CommonChat.proto", "System.proto", "SystemStruct.proto", "TestProtoBuff.proto" , "TestProtoBuffData.proto" };
            if (args.Length <= 0)
            {
                Console.WriteLine("请输入协议Proto文件名称（包含.proto)！！！");
            }
            else
            {
                Console.WriteLine("\r\n");
                DirectoryInfo protoFileFolder = new DirectoryInfo(Program.getProtoFilePath());
                if (!protoFileFolder.Exists)
                {
                    protoFileFolder.Create();
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("模板文件不存在！！！");
                    Program.waitKeyForExit();
                }
                if (protoFileFolder.GetFiles().Length < 1)
                {
                    Console.WriteLine("模板文件不存在！！！");
                    Program.waitKeyForExit();
                }
                DirectoryInfo cscFile = new DirectoryInfo(Program.getDotNet2Path());
                if (!cscFile.Exists)
                {
                    Console.WriteLine("请安装.NetFramework2.0！！！");
                    Program.waitKeyForExit();
                }
                Directory.CreateDirectory(string.Concat(new object[]
				{
					AppDomain.CurrentDomain.BaseDirectory,
					Path.DirectorySeparatorChar,
					"generate",
					Path.DirectorySeparatorChar,
					"java"
				}));
                Directory.CreateDirectory(string.Concat(new object[]
				{
					AppDomain.CurrentDomain.BaseDirectory,
					Path.DirectorySeparatorChar,
					"generate",
					Path.DirectorySeparatorChar,
					"csharp"
				}));
                string commProtoFileName = args[0];

                List<FileInfo> commProFiles = new List<FileInfo>();
                int protoFileCount=0;
                for(int i=0;i<args.Length;i++)
                {
                    FileInfo commFile = new FileInfo( Program.getCommProtoFilePath( args[i] ) );
                    if(commFile.Exists)
                    {
                        protoFileCount++;
                        commProFiles.Add( commFile );
                    }
                }

                //FileInfo commProtoFile = new FileInfo(Program.getCommProtoFilePath(commProtoFileName));
                if( protoFileCount <=0 )
                {
                    Console.WriteLine("ProtoFile:" + "不存在！！！");
                    Program.waitKeyForExit();
                }

                #region ToILR 替换
                string patternToILR = "[ToILR]\\nmessage\\s*[A-Za-z0-9]*\\s*{\\s*[A-Za-z0-9\\u4e00-\\u9fa5]*\\s*}";


                #endregion


                Dictionary<string, OpcodeInfo> communications = new Dictionary<string, OpcodeInfo>();
                int defaultIndex = 0;
                int spaceOpcode = 1000;
                string defaultRegion = "Default";
                string currentRegion = defaultRegion + defaultIndex;
                communications[currentRegion] = new OpcodeInfo();
                communications[currentRegion].startOpcode = spaceOpcode * defaultIndex;
                communications[currentRegion].endOpcode = spaceOpcode * (defaultIndex + 1);

                List<string> lines = new List<string>();

                string noOpDefinePattern = "//#no_opdefine\\s*[A-Za-z0-9\\u4e00-\\u9fa5]*\\s*";

                Console.WriteLine("文件列表:");

                for(int i = 0; i < commProFiles.Count; i++)
                {
                    var commProFile = commProFiles[i];
                    string[] slines = File.ReadAllLines(commProFile.FullName, Encoding.UTF8);

                    if(slines.Any(line => Regex.IsMatch(line, noOpDefinePattern)))
                    {
                        Console.WriteLine("[" + i + "]" + commProFile.Name + ": 文件包含no_opdefine标识，跳过该文件。");
                        continue;
                    }

                    Console.WriteLine("[" + i + "]" + commProFile.Name);

                    lines.AddRange(slines);
                }

                //string[] lines = File.ReadAllLines(commProtoFile.FullName, Encoding.UTF8);
                
                string pattern = "message\\s*[A-Za-z0-9]*\\s*{";
                //string pattern = "message\\s*[A-Za-z0-9]*\\s*[A-Za-z0-9]*\\s*{";
                string pattern2 = "message\\s*[A-Za-z0-9]*\\s*";
                string regionPattern = "//#region\\s*[A-Za-z0-9\\u4e00-\\u9fa5]*\\s*";
                string endregion = "//#endregion\\s*[A-Za-z0-9\\u4e00-\\u9fa5]*\\s*";
                string[] array = lines.ToArray();
                Dictionary<string, string> dic = new Dictionary<string, string>();
                List<string> strList = new List<string>();
                //int start = 0;
                //int index = 1;
                int endIndex = 0;
                int finalIndex = 0;
                StringBuilder sb = new StringBuilder();
                List<int> indexList = new List<int>();
                for (int i = 0; i < array.Length; i++)
                {
                    string line = array[i];
                    endIndex = 0;
                    //bool flag = true;

                    if (Regex.IsMatch(line, regionPattern))
                    {
                        string regionName = line.Replace("//#region", "").Replace("{", "").Trim();
                        currentRegion = regionName;
                        string[] ps = line.Split(new char[]
						{
							' '
						}, StringSplitOptions.RemoveEmptyEntries);
                        int opcode = -1;
                        string[] array2 = ps;
                        for (int j = 0; j < array2.Length; j++)
                        {
                            string tmp = array2[j];
                            int.TryParse(tmp, out opcode);
                            if (opcode > 0)
                            {
                                break;
                            }
                        }
                        if (opcode < 0)
                        {
                            Console.WriteLine(line + " 错误格式");
                            return;
                        }
                        communications[currentRegion] = new OpcodeInfo();
                        communications[currentRegion].startOpcode = opcode;

                        //start = opcode;
                        //sb.AppendLine(line);
                        //index = 1;
                        //flag = false;
                    }
                    if (Regex.IsMatch(line, endregion))
                    {
                        string[] ps = line.Split(new char[]
						{
							' '
						}, StringSplitOptions.RemoveEmptyEntries);
                        int opcode = -1;
                        string[] array2 = ps;
                        for (int j = 0; j < array2.Length; j++)
                        {
                            string tmp = array2[j];
                            int.TryParse(tmp, out opcode);
                            if (opcode > 0)
                            {
                                break;
                            }
                        }
                        if (opcode < 0)
                        {
                            Console.WriteLine(line + " 错误格式");
                            return;
                        }
                        communications[currentRegion].endOpcode = opcode;
                        defaultIndex++;
                        currentRegion = string.Concat(new object[]
						{
							defaultRegion,
							defaultIndex,
							" ",
							(spaceOpcode * defaultIndex).ToString()
						});
                        communications[currentRegion] = new OpcodeInfo();
                        communications[currentRegion].startOpcode = spaceOpcode * defaultIndex;
                        communications[currentRegion].endOpcode = spaceOpcode * (defaultIndex + 1);
                        endIndex = opcode;
                        if (finalIndex > endIndex && endIndex != 0)
                        {
                            Console.WriteLine(finalIndex + " 编号超出" + "最大编号" + endIndex);
                            return;
                        }

                        //sb.AppendLine(line);
                        //flag = false;
                    }
                    if ((Regex.IsMatch(line, pattern) || Regex.IsMatch(line, pattern2)) && line.IndexOf("java_package") < 0)
                    {
                        
                        string commName = line.Replace("message", "").Replace("{", "").Trim();
                        string commNum = line.Replace("message", "").Replace("//", "").Replace("{", "").Trim();

                        int annotationIndex = commName.IndexOf("//");
                        if (annotationIndex != -1)
                        {
                            commName = commName.Substring(0, annotationIndex).Trim();
                            commNum = commNum.Replace(commName, "").Trim();

                        }
                        communications[currentRegion].messages.Add(commName);
                        //communications[currentRegion].index.Add(commNum);
                        communications[currentRegion].dicMessages[commNum] = commName;
                        string sss = "\\d[0-9]*";
                        string strNum = commNum;
                        if (strNum == null)
                        {
                            Console.WriteLine(line + " 错误格式,未填写编号");
                            return;
                        }
                        int strIndex = strNum.IndexOf("/*");
                        if (strIndex != -1)
                        {
                            strNum = strNum.Substring(0, strIndex).Trim();
                        }
                        if (Regex.IsMatch(strNum, sss))
                        {
                            //Console.WriteLine(line + " 编号超出" + strNum);
                            int theIndex = int.Parse(strNum);
                            if (theIndex > endIndex && endIndex != 0)
                            {
                                Console.WriteLine(theIndex + " 编号超出" + "最大编号" + endIndex);
                                return;
                            }
                        }
                        else
                        {
                            Console.WriteLine(line + " 错误格式");
                            return;
                        }
                        finalIndex = int.Parse(strNum);
                        bool ifFind = false;
                        if (indexList != null)
                        {
                            //ifFind = indexList.Find(a => a == finalIndex);
                            ifFind = indexList.Contains(finalIndex);
                        }
                        if (ifFind)
                        {
                            Console.WriteLine(line + " 编号重复" + "重复编号" + finalIndex);
                            return;
                        }
                        indexList.Add(finalIndex);

                        //注释生成
                        //sb.AppendLine(string.Concat(new object[]
                        //{
                        //    line,
                        //    " ",
                        //    "//",
                        //    start+index,
                        //}));
                        //flag = false;
                        //index++;
                    }

                    //if (flag)
                    //{
                    //    sb.AppendLine(line);
                    //}
                }
                //
                //FileInfo fileInfo = new FileInfo("..//PBM.proto");
                //if (fileInfo.Exists)
                //{
                //    fileInfo.Delete();
                //}
                //File.WriteAllText(fileInfo.FullName, sb.ToString(), new UTF8Encoding());


                string java_package = "com.hcwy.h5.communication";
                string cs_name_space = "Com.Hcwy.H5.Communication";
                //if( args.Length >= args.Length)
                //{
                    java_package = args[args.Length-2];
                //}
                //if (args.Length >= 3)
                //{
                    cs_name_space = args[args.Length-1];
                //}
                GenerateFile.generate(communications, java_package, cs_name_space);
            }
        }
    }
}
